from flask import Flask, render_template, jsonify, request, redirect, url_for
from flask_socketio import SocketIO
import threading
import sys
import os
import json
import time
from datetime import datetime
import logging

# 添加父目录到系统路径
current_dir = os.path.dirname(os.path.abspath(__file__))
parent_dir = os.path.dirname(current_dir)
sys.path.append(parent_dir)

# 设置日志处理
class WebLogHandler(logging.Handler):
    def __init__(self, socketio):
        super().__init__()
        self.socketio = socketio
        self.logs = []
        self.max_logs = 1000
        
    def emit(self, record):
        log_entry = self.format(record)
        self.logs.append({
            'time': datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
            'level': record.levelname,
            'message': record.getMessage()
        })
        
        if len(self.logs) > self.max_logs:
            self.logs.pop(0)
            
        self.socketio.emit('log_update', {
            'log': log_entry,
            'level': record.levelname
        })

# 创建Flask应用
app = Flask(__name__, 
            static_folder=os.path.join(current_dir, 'static'),
            template_folder=os.path.join(current_dir, 'templates'))
app.config['SECRET_KEY'] = 'stock_ai_dashboard_secret'
socketio = SocketIO(app)

# 共享的应用实例
stock_app = None

@app.route('/')
def index():
    """主页 - 系统概览"""
    return render_template('index.html')

@app.route('/stocks')
def stocks():
    """股票列表页"""
    if not stock_app:
        return jsonify({"error": "System not initialized"}), 500
        
    # 从配置获取股票列表
    stock_list = stock_app.config['monitoring']['stock_list']
    
    # 获取每只股票的最新分析结果
    stock_data = []
    for stock_code in stock_list:
        try:
            latest_result = stock_app.db_manager.get_latest_analysis(stock_code)
            if latest_result:
                stock_info = stock_app.stock_data_collector.get_realtime_quotes([stock_code])
                stock_name = stock_info.iloc[0]['name'] if not stock_info.empty else stock_code
                
                # 获取最新策略
                latest_strategy = stock_app.db_manager.get_latest_strategy(stock_code, "short")
                
                stock_data.append({
                    'code': stock_code,
                    'name': stock_name,
                    'price': stock_info.iloc[0]['close'] if not stock_info.empty else 0,
                    'change': stock_info.iloc[0]['change'] if not stock_info.empty else 0,
                    'summary': latest_result.get('content', {}).get('summary', 'No summary'),
                    'strategy': latest_strategy.get('action', 'No strategy'),
                    'confidence': latest_strategy.get('confidence', 'unknown'),
                    'last_updated': latest_result.get('timestamp', '').strftime('%Y-%m-%d %H:%M:%S') 
                        if 'timestamp' in latest_result else 'Unknown'
                })
            else:
                stock_data.append({
                    'code': stock_code,
                    'name': 'Unknown',
                    'summary': 'No analysis available',
                    'strategy': 'No strategy available',
                    'last_updated': 'Never'
                })
        except Exception as e:
            app.logger.error(f"Error fetching data for {stock_code}: {str(e)}")
            stock_data.append({
                'code': stock_code,
                'name': 'Error',
                'summary': f'Error: {str(e)}',
                'strategy': 'Error',
                'last_updated': 'Error'
            })
    
    return render_template('stocks.html', stocks=stock_data)

@app.route('/stock/<stock_code>')
def stock_detail(stock_code):
    """股票详情页"""
    if not stock_app:
        return jsonify({"error": "System not initialized"}), 500
    
    try:
        # 获取股票基本信息
        stock_info = stock_app.stock_data_collector.get_realtime_quotes([stock_code])
        stock_name = stock_info.iloc[0]['name'] if not stock_info.empty else stock_code
        
        # 获取分析结果
        technical = stock_app.db_manager.get_latest_analysis(stock_code, "technical")
        fundamental = stock_app.db_manager.get_latest_analysis(stock_code, "fundamental")
        summary = stock_app.db_manager.get_latest_analysis(stock_code, "summary")
        
        # 获取策略
        short_strategy = stock_app.db_manager.get_latest_strategy(stock_code, "short")
        medium_strategy = stock_app.db_manager.get_latest_strategy(stock_code, "medium")
        long_strategy = stock_app.db_manager.get_latest_strategy(stock_code, "long")
        
        # 历史数据
        historical_data = stock_app.stock_data_collector.get_daily_data(
            stock_code, 
            limit=30, 
            end_date=datetime.now().strftime('%Y%m%d')
        )
        
        # 转换为图表数据格式
        chart_data = []
        if not historical_data.empty:
            for _, row in historical_data.iterrows():
                chart_data.append({
                    'date': row.name.strftime('%Y-%m-%d') if hasattr(row.name, 'strftime') else str(row.name),
                    'open': float(row['open']),
                    'high': float(row['high']),
                    'low': float(row['low']),
                    'close': float(row['close']),
                    'volume': float(row['vol'])
                })
                
        # 反转列表使日期按升序排列
        chart_data.reverse()
        
        return render_template(
            'stock_detail.html',
            stock=stock_code,
            stock_name=stock_name,
            technical=technical.get('content', {}) if technical else {},
            fundamental=fundamental.get('content', {}) if fundamental else {},
            summary=summary.get('content', {}) if summary else {},
            short_strategy=short_strategy,
            medium_strategy=medium_strategy,
            long_strategy=long_strategy,
            chart_data=json.dumps(chart_data),
            last_price=stock_info.iloc[0]['close'] if not stock_info.empty else 0,
            change=stock_info.iloc[0]['change'] if not stock_info.empty else 0,
            last_updated=summary.get('timestamp', datetime.now()).strftime('%Y-%m-%d %H:%M:%S') 
                if summary and 'timestamp' in summary else 'Unknown'
        )
    except Exception as e:
        app.logger.error(f"Error in stock detail for {stock_code}: {str(e)}")
        return render_template('error.html', error=str(e), title=f"Error loading {stock_code}")

@app.route('/status')
def status():
    """系统状态页"""
    if not stock_app:
        return jsonify({"error": "System not initialized"}), 500
    
    health = stock_app.check_health()
    
    # 获取性能指标
    performance = []
    try:
        perf_data = stock_app.db_manager.get_performance_metrics(limit=20)
        for item in perf_data:
            performance.append({
                'operation': item.get('operation', 'unknown'),
                'stock_code': item.get('stock_code', ''),
                'duration': f"{item.get('duration', 0):.2f}s",
                'timestamp': item.get('timestamp', datetime.now()).strftime('%Y-%m-%d %H:%M:%S')
            })
    except Exception as e:
        app.logger.error(f"Error fetching performance metrics: {str(e)}")
    
    return render_template('status.html', 
                          health=health, 
                          uptime="Unknown",  # 可以计算启动时间与当前时间的差值
                          performance=performance)

@app.route('/logs')
def logs():
    """日志页面"""
    # 读取最新的日志文件内容
    try:
        with open('app.log', 'r') as f:
            log_content = f.readlines()
            # 限制行数，防止页面过大
            if len(log_content) > 1000:
                log_content = log_content[-1000:]
    except Exception as e:
        log_content = [f"Error reading log file: {str(e)}"]
    
    return render_template('logs.html', logs=log_content)

@app.route('/api/health')
def api_health():
    """健康状态API"""
    if not stock_app:
        return jsonify({"status": "error", "message": "System not initialized"}), 500
    
    return jsonify(stock_app.check_health())

@app.route('/api/stocks')
def api_stocks():
    """API: 获取所有监控的股票列表"""
    try:
        # 尝试从实际数据库获取数据
        stocks = []
        if stock_app:
            stock_list = stock_app.config['monitoring']['stock_list']
            for stock_code in stock_list:
                # 获取最近的分析结果
                analysis = stock_app.db_manager.get_latest_analysis(stock_code) 
                strategy = stock_app.db_manager.get_latest_strategy(stock_code, 'short')
                
                # 如果没有数据，使用模拟数据
                if not analysis or not strategy:
                    stocks.append(get_mock_stock_data(stock_code))
                else:
                    stocks.append({
                        'code': stock_code,
                        'name': get_stock_name(stock_code),
                        'price': analysis.get('price', '--'),
                        'change': analysis.get('change', 0),
                        'summary': analysis.get('result', {}).get('summary', '暂无分析'),
                        'strategy': strategy.get('strategy', {}).get('action', '观望'),
                        'confidence': strategy.get('strategy', {}).get('confidence', 'medium'),
                        'last_updated': analysis.get('timestamp', datetime.now()).strftime('%Y-%m-%d %H:%M')
                    })
        
        # 如果没有数据，返回模拟数据
        if not stocks:
            stocks = [get_mock_stock_data(code) for code in ['000001.SZ', '600036.SH', '601318.SH']]
        
        return jsonify(stocks)
    except Exception as e:
        logger.error(f"获取股票列表失败: {str(e)}")
        # 返回模拟数据
        mock_stocks = [get_mock_stock_data(code) for code in ['000001.SZ', '600036.SH', '601318.SH']]
        return jsonify(mock_stocks)

def get_mock_stock_data(stock_code):
    """生成模拟股票数据"""
    stock_names = {
        '000001.SZ': '平安银行',
        '600036.SH': '招商银行',
        '601318.SH': '中国平安',
        '000333.SZ': '美的集团',
        '600519.SH': '贵州茅台'
    }
    
    name = stock_names.get(stock_code, f'股票{stock_code}')
    base_price = 10.0 + (hash(stock_code) % 100)
    change_pct = round((hash(stock_code[::-1]) % 10 - 5) / 100, 4)
    
    return {
        'code': stock_code,
        'name': name,
        'price': str(round(base_price, 2)),
        'change': round(change_pct * 100, 2),
        'summary': f'这是{name}({stock_code})的模拟分析摘要。由于当前系统正在演示模式运行，此处显示的是模拟数据。该股票近期表现' + ('良好' if change_pct > 0 else '一般') + '，交易量适中。',
        'strategy': '买入' if change_pct > 0.01 else ('卖出' if change_pct < -0.01 else '观望'),
        'confidence': 'medium',
        'last_updated': datetime.now().strftime('%Y-%m-%d %H:%M')
    }

@app.route('/api/stock/<stock_code>')
def api_stock_detail(stock_code):
    """单个股票详情API"""
    if not stock_app:
        return jsonify({"error": "System not initialized"}), 500
    
    technical = stock_app.db_manager.get_latest_analysis(stock_code, "technical")
    fundamental = stock_app.db_manager.get_latest_analysis(stock_code, "fundamental")
    summary = stock_app.db_manager.get_latest_analysis(stock_code, "summary")
    
    short_strategy = stock_app.db_manager.get_latest_strategy(stock_code, "short")
    medium_strategy = stock_app.db_manager.get_latest_strategy(stock_code, "medium")
    long_strategy = stock_app.db_manager.get_latest_strategy(stock_code, "long")
    
    result = {
        'stock_code': stock_code,
        'technical': technical.get('content', {}) if technical else {},
        'fundamental': fundamental.get('content', {}) if fundamental else {},
        'summary': summary.get('content', {}) if summary else {},
        'strategies': {
            'short': short_strategy,
            'medium': medium_strategy,
            'long': long_strategy
        }
    }
    
    return jsonify(result)

@app.route('/api/analyze', methods=['POST'])
def api_analyze():
    """触发分析API"""
    if not stock_app:
        return jsonify({"error": "System not initialized"}), 500
    
    data = request.json
    if not data or 'stock_code' not in data:
        return jsonify({"error": "Missing stock_code parameter"}), 400
    
    stock_code = data['stock_code']
    analyzer_type = data.get('analyzer_type', None)
    
    try:
        # 使用线程执行分析，以免阻塞API响应
        def run_analysis():
            result = stock_app.analyze_stock(stock_code, analyzer_type)
            socketio.emit('analysis_complete', {
                'stock_code': stock_code,
                'success': 'error' not in result
            })
        
        threading.Thread(target=run_analysis).start()
        return jsonify({"status": "success", "message": f"Analysis started for {stock_code}"})
    except Exception as e:
        return jsonify({"error": str(e)}), 500

@socketio.on('connect')
def handle_connect():
    """处理WebSocket连接"""
    socketio.emit('status', {'status': 'connected'})

@socketio.on('request_logs')
def handle_request_logs():
    """发送最新日志"""
    # 读取最新日志并发送
    try:
        with open('app.log', 'r') as f:
            log_content = f.readlines()
            # 限制行数
            if len(log_content) > 100:
                log_content = log_content[-100:]
        socketio.emit('initial_logs', {'logs': log_content})
    except Exception as e:
        socketio.emit('initial_logs', {'logs': [f"Error reading log file: {str(e)}"]})

def start_web_server(stock_analysis_app, port=5000):
    """启动Web服务器"""
    global stock_app
    stock_app = stock_analysis_app
    
    # 添加Web日志处理器
    web_log_handler = WebLogHandler(socketio)
    web_log_handler.setLevel(logging.INFO)
    formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
    web_log_handler.setFormatter(formatter)
    
    # 添加到根日志记录器
    root_logger = logging.getLogger()
    root_logger.addHandler(web_log_handler)
    
    # 启动Web服务器
    socketio.run(app, host='0.0.0.0', port=port, debug=False, allow_unsafe_werkzeug=True) 